PROJECT = "ESP32_smart-card"
VERSION = "1.7.0"
--[[
        V1.7.0-build1001适用于：
        *【ESP32】物联网智能卡Ver7.0 *
        update log:
        1.优化体验
        2.新增俄罗斯方块小游戏（做不成）
]]


uw_name1="SuperWIFI-k"--智能卡优先连接Wifi的名称
uw_password1="IEEE802.11ax"--智能卡优先连接Wifi的密码
uw_name2="ConfigWIFI"--智能卡备选连接Wifi的名称（可脱离电脑切换）
uw_password2="smartconfig"--智能卡备选连接Wifi的密码（可脱离电脑切换）


sys = require "sys"--不管干啥，先写上这个
poweron=0--初始化变量0：已开机，但未完成初始化进程 1：已开机，已完成初始化，可正常使用


sys.taskInit(function() --设备初始化线程,我敢保证这东西只会执行一次

        if poweron==0 then

        --u8g2_OLED驱动初始化
        u8g2.begin({ic = "ssd1306",direction = 0,mode="i2c_hw",i2c_id=0})--智能卡V7支持硬件I2C
        u8g2.SetFont(u8g2.font_opposansm10_chinese)                      --配置U8G2字体（中文10号字体）
        --u8g2.SetFont(u8g2.font_opposansm12_chinese)                    --12号中文字体（需要特定固件）

        --按键阵列GPIO初始化
        gpio.setup(2,nil,gpio.PULLUP)--上
        gpio.setup(6,nil,gpio.PULLUP)--左
        gpio.setup(10,nil,gpio.PULLUP)--下
        gpio.setup(3,nil,gpio.PULLUP)--右

        --其他GPIO初始化
        gpio.setup(8,0)  --初始化板载LED的GPIO为低电平
        gpio.setup(12,nil,gpio.PULLUP)--电源输入端检测 1:外置电源供电 0:电池供电 *第七代智能卡设计缺陷，目前该功能暂不可用
        gpio.setup(7,1,gpio.PULLUP)--电量显示 1：打开显示 0：关闭显示

        --变量定义及初始化(全局变量)
        led_mode = 0 -- 0：关闭 1：常亮  2：呼吸
        pwled_mode = 1 --1：开启 0：关闭
        page = 0   -- 0：主  -1：板载LED配置 -2：电量指示灯配置 1：环境数据  11：WIFI配置 12：WIFI连接配置 -11：MCU速度配置 21:小游戏
        pled_time = 0  --控制PWM呼吸占空比
        pled_sw = 0  --切换PWM呼吸状态（渐亮/渐暗）
        clk_sw = 160 --控制MCU主频（80/160,默认160MHz）
        wlan_mode = 0 --控制WIFI模式 0:STATION模式 1:AP模式（还没做好）
        wlan_connect = 0 --控制连接不同的WiFi 0：首选wifi 1：备选wifi
        startnum,finishnum=0,100--猜数小游戏两个极点

        --WIFI功能初始化（默认station模式）
        wlan.init()--初始化WIFI
        wlan.setMode(wlan.STATION)--默认为station模式
        wlan.setMac(1, string.fromHex("60AAF973090E"))--配置MAC地址（AP和station模式共用一个MAC）
        wlan.setMac(0, string.fromHex("60AAF973090E"))--看官方的wiki
        wlan.setHostname("ESP32-IOT-CARD")--配置智能卡名称
        wlan.setps(wlan.PS_NONE)--不使用WIFI省电
        wlan.dhcp(1)--开启DHCP服务

        --尝试NTP对时
        rtctime_set={year=2021,mon=12,day=31,hour=16,min=0,sec=0}--先设置一个，后面NTP会校准(如果跳过NTP校准将显示系统运行时间)
        rtc.set(rtctime_set)--把上面设置的内容加载到rtc里面
        sys.publish("startNTP")--启动MTP配网线程，初始化完成

        poweron=1
        end
end)


sys.taskInit(function ()        --主线程
        sys.waitUntil("NTPOK")
        while true do--循环执行
                sys.wait(100)
                if page==0 then
                        u8g2.ClearBuffer()
                        rtctime_get = rtc.get()--获取RTC时钟的数据*（注意，这东西的返回值是table，需要用table的语法进行操作)
                        --下面这个鬼东西用来获取一大堆的数据（虽然乱，但是能用）
                        g_year,g_mon,g_day,g_hour,g_min,g_sec = rtctime_get["year"],rtctime_get["mon"],rtctime_get["day"],rtctime_get["hour"],rtctime_get["min"],rtctime_get["sec"]
                        u8g2.DrawUTF8("智能卡状态",30,15)
                        u8g2.DrawUTF8("时钟频率--"..mcu.getClk().."MHz",0,30)--MCU速度会优先由是否为电池供电自动调整，再由用户手动调整

                        --由WIFI模式决定显示内容
                        if wlan.getMode()==1 and wlan.ready()==true then
                                u8g2.DrawUTF8("WIFI模式--".."STA-OK",0,45)
                        elseif wlan.getMode()==1 and wlan.ready()==false then
                                u8g2.DrawUTF8("WIFI模式--".."STA-NO",0,45)
                        elseif wlan.getMode()==2 and wlan.ready()==true then
                                u8g2.DrawUTF8("WIFI模式--".."AP-OK",0,45)
                        elseif wlan.getMode()==2 and wlan.ready()==false then
                                u8g2.DrawUTF8("WIFI模式--".."AP-NO",0,45)
                        end

                        if g_hour<=9 then--加0凑数，下面都是如此
                                g_hour="0"..g_hour
                        end
                        if g_min<=9 then
                                g_min="0"..g_min
                        end
                        if g_sec<=9 then
                                g_sec="0"..g_sec
                        end

                        u8g2.DrawUTF8(g_year.."."..g_mon.."."..g_day.." "..g_hour..":"..g_min..":"..g_sec,0,60)
                        u8g2.SendBuffer()

                        if gpio.get(6)==0 then
                                page=-1
                        elseif gpio.get(3)==0 then
                                page=1
                        elseif gpio.get(10)==0 then
                                page=-11
                        elseif gpio.get(2)==0 then
                                page=11
                        end
                end

                if page==-1 and led_mode==0 then
                        u8g2.ClearBuffer()
                        u8g2.DrawUTF8("板载LED配置",25,15)
                        u8g2.DrawUTF8("常亮",0,30)
                        u8g2.DrawUTF8("关闭".."--当前选择",0,45)
                        u8g2.DrawUTF8("呼吸",0,60)
                        u8g2.SendBuffer()

                        if gpio.get(2)==0 then
                                led_mode=1
                        elseif gpio.get(10)==0 then
                                led_mode=2
                        end
                        if gpio.get(3)==0 then
                                page=0
                        elseif gpio.get(6)==0 then
                                page=-2
                        end
                end
                if page==-1 and led_mode==1 then
                        u8g2.ClearBuffer()
                        u8g2.DrawUTF8("板载LED配置",25,15)
                        u8g2.DrawUTF8("常亮".."--当前选择",0,30)
                        u8g2.DrawUTF8("关闭",0,45)
                        u8g2.DrawUTF8("呼吸",0,60)
                        u8g2.SendBuffer()

                        if gpio.get(10)==0 then
                                led_mode=0
                        end
                        if gpio.get(3)==0 then
                                page=0
                        elseif gpio.get(6)==0 then
                                page=-2
                        end
                end
                if page==-1 and led_mode==2 then
                        u8g2.ClearBuffer()
                        u8g2.DrawUTF8("板载LED配置",25,15)
                        u8g2.DrawUTF8("常亮",0,30)
                        u8g2.DrawUTF8("关闭",0,45)
                        u8g2.DrawUTF8("呼吸".."--当前选择",0,60)
                        u8g2.SendBuffer()

                        if gpio.get(2)==0 then
                                led_mode=0
                        end
                        if gpio.get(3)==0 then
                                page=0
                        elseif gpio.get(6)==0 then
                                page=-2
                        end
                end

                if page==-2 and pwled_mode==1 then
                        u8g2.ClearBuffer()
                        u8g2.DrawUTF8("电量指示灯配置",15,15)
                        u8g2.DrawUTF8("开启".."--当前选择",0,30)
                        u8g2.DrawUTF8("关闭",0,45)
                        u8g2.SendBuffer()
                        if gpio.get(10)==0 then
                                gpio.set(7,0)
                                pwled_mode=0
                        end
                        if gpio.get(3)==0 then
                                page=-1
                        end
                end
                if page==-2 and pwled_mode==0 then
                        u8g2.ClearBuffer()
                        u8g2.DrawUTF8("电量指示灯配置",15,15)
                        u8g2.DrawUTF8("开启",0,30)
                        u8g2.DrawUTF8("关闭".."--当前选择",0,45)
                        u8g2.SendBuffer()
                        if gpio.get(2)==0 then
                                gpio.set(7,1)
                                pwled_mode=1
                        end
                        if gpio.get(3)==0 then
                                page=-1
                        end
                end

                if page==1 then
                        u8g2.ClearBuffer()
                        u8g2.DrawUTF8("环境数据",35,15)--每两秒更新一次数据（由后面的另一个协程完成）
                                u8g2.DrawUTF8("温度--"..dht10_t.."*C",0,30)
                                u8g2.DrawUTF8("湿度--"..dht10_h.."%",0,45)
                        u8g2.DrawUTF8("*更新于2s前",0,60)
                        u8g2.SendBuffer()

                        if gpio.get(6)==0 then
                                page=0
                        end
                end

                if page==-11 and clk_sw==160 then
                        u8g2.ClearBuffer()
                        u8g2.DrawUTF8("MCU时钟速度",20,15)
                        u8g2.DrawUTF8("- 使用左右键切换 +",5,30)
                        u8g2.DrawUTF8("160MHz",35,45)
                        u8g2.DrawUTF8("高性能",40,60)
                        u8g2.SendBuffer()

                        if gpio.get(6)==0 then
                                mcu.setClk(80)
                                clk_sw=80
                        end
                        if gpio.get(2)==0 then
                                page=0
                        end
                end
                if page==-11 and clk_sw==80 then
                        u8g2.ClearBuffer()
                        u8g2.DrawUTF8("MCU时钟速度",20,15)
                        u8g2.DrawUTF8("- 使用左右键切换 +",5,30)
                        u8g2.DrawUTF8("80MHz",40,45)
                        u8g2.DrawUTF8("均衡",45,60)
                        u8g2.SendBuffer()

                        if gpio.get(3)==0 then
                                mcu.setClk(160)
                                clk_sw=160
                        end
                        if gpio.get(2)==0 then
                                page=0
                        end
                end

                if page==11 and wlan_mode==0 then
                        u8g2.ClearBuffer()
                        u8g2.DrawUTF8("WIFI模式",35,15)
                        u8g2.DrawUTF8("S 使用左右键切换 A",5,30)
                        u8g2.DrawUTF8("STATION模式",20,45)
                        u8g2.DrawUTF8("智能卡连接WLAN",10,60)
                        u8g2.SendBuffer()

                        if gpio.get(3)==0 then
                                wlan_mode=1
                        elseif gpio.get(10)==0 then
                                page=0
                        elseif gpio.get(2)==0 and wlan.ready()==false then
                                page=12
                        end
                end
                if page==11 and wlan_mode==1 then
                        u8g2.ClearBuffer()
                        u8g2.DrawUTF8("WIFI模式",35,15)
                        u8g2.DrawUTF8("S 使用左右键切换 A",5,30)
                        u8g2.DrawUTF8("AP模式",40,45)
                        u8g2.DrawUTF8("AP模式正在开发",15,60)
                        --wlan.createAP("ESP32-IOT-CARD","ofcourseISLY32")
                        u8g2.SendBuffer()

                        if gpio.get(6)==0 then
                                --wlan.setMode(wlan.STATION)
                                wlan_mode=0
                        elseif gpio.get(10)==0 then
                                page=0
                        elseif gpio.get(2)==0 and wlan.ready()==false then
                                page=12
                        end
                end

                if page==12 and wlan_connect==0 then
                        u8g2.ClearBuffer()
                        u8g2.DrawUTF8("使用左右键切换",15,30)
                        u8g2.DrawUTF8(uw_name1,0,45)
                        u8g2.DrawUTF8("WIFI连接",35,15)
                        wlan.disconnect()
                        wlan.connect(uw_name1,uw_password1,1)
                        u8g2.SendBuffer()

                        if gpio.get(3)==0 then
                                wlan_connect=1
                        elseif gpio.get(10)==0 then
                                page=11
                        end
                end
                if page==12 and wlan_connect==1 then
                        u8g2.ClearBuffer()
                        u8g2.DrawUTF8("使用左右键切换",15,30)
                        u8g2.DrawUTF8(uw_name2,0,45)
                        u8g2.DrawUTF8("WIFI连接",35,15)
                        wlan.disconnect()
                        wlan.connect(uw_name2,uw_password2,1)
                        u8g2.SendBuffer()

                        if gpio.get(6)==0 then
                                wlan_connect=0
                        elseif gpio.get(10)==0 then
                                page=11
                        end
                end

                if gpio.get(6)==0 and gpio.get(3)==0 then--左右键同时按下
                        page=21
                        gameok=0
                        end

                if page==21 and gameok==0 then
                        u8g2.ClearBuffer()
                        u8g2.DrawUTF8("小游戏(beta)",20,15)
                        u8g2.DrawUTF8("二分法猜数",30,30)
                        u8g2.DrawUTF8("这个数字也许是: ".."50",0,45)
                        u8g2.DrawUTF8("大了?       小了?",10,60)
                        u8g2.SendBuffer()
                        sys.wait(1000)
                        gameok=1        --1s的延迟，防止误触
                end

                if page==21 and gameok==1 then
                        u8g2.ClearBuffer()
                        u8g2.DrawUTF8("小游戏(beta)",20,15)
                        u8g2.DrawUTF8("二分法猜数",30,30)
                        halfnum=(finishnum+startnum)/2
                        if halfnum<10 then
                                s_halfnum = string.sub (tostring(halfnum),1,1)--s_代表字符串形式
                        elseif halfnum>=10 and halfnum<99.5 then
                                s_halfnum = string.sub (tostring(halfnum),1,2)
                        elseif halfnum>=99.5 then
                                s_halfnum = "100"
                        end
                        u8g2.DrawUTF8("这个数字也许是: "..s_halfnum,0,45)
                        u8g2.DrawUTF8("大了?       小了?",10,60)
                        u8g2.SendBuffer()
                        if gpio.get(6)==0 then
                                startnum=startnum
                                finishnum=halfnum
                        elseif gpio.get(3)==0 then
                                startnum=halfnum
                                finishnum=finishnum
                        elseif gpio.get(2)==0 and gpio.get(10)==0 then
                                page=0
                                gameok=0
                                startnum,finishnum=0,100
                        end
                end


                if led_mode==0 then     --检测led_mode这个变量，控制板载LED
                        pwm.open(8,2400,0)
                elseif led_mode==1 then
                        pwm.open(8,2400,10000)
                elseif led_mode==2 then
                        pwm.open(8,2400,pled_time)
                        if pled_time<1001 and pled_sw==0 then
                        pled_time=pled_time+25
                        end
                        if pled_time==800 then--最高亮度
                        pled_sw=1
                        end
                        if pled_time<10001 and pled_sw==1 then
                        pled_time=pled_time-25
                        end
                        if pled_time==300 then--最低亮度
                        pled_sw=0
                        end
                end



end--这个是while true的end
end)--这个是fuction的end

sys.taskInit(function () --NTP配网线程（只会在开机时出现）
        sys.waitUntil("startNTP")
        local ntp_page=0
        u8g2.ClearBuffer()
        u8g2.DrawUTF8("需校准RTC时钟",15,15)
        u8g2.DrawUTF8("按下键启动校准",15,30)
        u8g2.SendBuffer()
        gpio.set(8,1)
        sys.wait(100)
        gpio.set(8,0)
        sys.wait(100)
        gpio.set(8,1)
        sys.wait(100)
        gpio.set(8,0)
        while true do
                sys.wait(100)

                if gpio.get(2)==0 then--跳过校准
                        sys.publish("NTPOK")
                        break
                end

                if ntp_page==0 then
                        u8g2.ClearBuffer()
                        u8g2.DrawUTF8("需校准RTC时钟",15,15)
                        u8g2.DrawUTF8("按下键启动校准",15,30)
                        u8g2.DrawUTF8(uw_name1,0,45)
                        u8g2.SendBuffer()

                        if gpio.get(3)==0 then
                                ntp_page=1
                        end
                elseif ntp_page==1 then
                        u8g2.ClearBuffer()
                        u8g2.DrawUTF8("需校准RTC时钟",15,15)
                        u8g2.DrawUTF8("按下键启动校准",15,30)
                        u8g2.DrawUTF8(uw_name2,0,45)
                        u8g2.SendBuffer()

                        if gpio.get(6)==0 then
                                ntp_page=0
                        end
                end

                if gpio.get(10)==0 then--开始校准RTC
                        if ntp_page==0 then
                                wlan.disconnect()
                                wlan.connect(uw_name1,uw_password1,1)
                                u8g2.DrawUTF8("正在联网对时",0,60)
                                u8g2.SendBuffer()
                                break
                        elseif ntp_page==1 then
                                wlan.disconnect()
                                wlan.connect(uw_name2,uw_password2,1)
                                u8g2.DrawUTF8("正在联网对时",0,60)
                                u8g2.SendBuffer()
                                break
                        end

                end
        end

        ntp.init("ntp.ntsc.ac.cn")--中科院国家授时中心
        ntp.settz("CST-8")
end)

sys.taskInit(function ()
        sys.waitUntil("NTPOK")
        while true do
                dht10_h,dht10_t,dht10_r = sensor.dht1x(8, true)--dht10_h:湿度 dht10_t:温度 r:返回值（true/false）
                if dht10_r==true then
                        dht10_t = string.sub (tostring(dht10_t/100),1,2)
                        dht10_h = string.sub (tostring(dht10_h/100),1,2)
                else
                        dht10_t ="ERROR"
                        dht10_h ="ERROR"
                end
                sys.wait(2000)
        end

end)

sys.subscribe("NTP_SYNC_DONE",
                function()
                        sys.publish("NTPOK")
                end
)

sys.run()
